package com.huangdada.hfweather.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huangdada.hfweather.bean.City;
import com.huangdada.hfweather.bean.Weather;
import com.huangdada.hfweather.service.CityService;
import com.huangdada.hfweather.service.WeatherService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.StringUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Description: 获取天气状况任务
 * @PROJECT_NAME: hf-weather
 * @CLASS_NAME:
 * @Author: huanglibin
 * @Date: 2020-03-31 0:16
 * @Version: 1.0
 */
@Slf4j
public class WeatherJob extends QuartzJobBean {

    /**
     * 创建一个线程池
     */
    private static ThreadPoolExecutor threadPoolExecutor;

    static {
        threadPoolExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>());
    }

    @Autowired
    private WeatherService weatherService;

    @Autowired
    private CityService cityService;

    /**
     * 查询的地区
     */
    private String location;

    public WeatherJob(String location) {
        this.location = location;
    }

    public WeatherJob() {
    }

    /**
     * 应用KEY
     */
    private final String KEY = "97a3e5ec3abd44aab23dcc2171fa975c";

    /**
     * 实现QuartzJobBean的executeInternal()方法，即可定义工作内容
     *
     * @param jobExecutionContext
     * @throws JobExecutionException
     */
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        log.info("获取实况天气任务开始....");
        List<City> cityList = cityService.getCityList();
        if (cityList != null && cityList.size() > 0) {
            log.info("执行线程池任务....");
            threadPoolExecutor.execute(new WeatherRunnable(cityList));
        } else {
            log.info("获取城市列表失败...");
        }
        log.info("获取实况天气任务结束...");
    }

    private class WeatherRunnable implements Runnable {
        List<City> cityList;

        public WeatherRunnable(List<City> cityList) {
            this.cityList = cityList;
        }

        @Override
        public void run() {
            //遍历城市获取
            for (City city : cityList) {
                String cityId = city.getCityId();
                execute(cityId);
            }
        }
    }

    /**
     * 执行方法
     *
     * @param cityId
     */
    private void execute(String cityId) {
        //参数字符串拼接
        String param = "key=" + KEY + "&location=" + cityId;
        StringBuilder sb = new StringBuilder();
        InputStream is = null;
        BufferedReader br = null;
        PrintWriter out = null;
        int count = 3;
        boolean flag = false;
        try {
            //接口地址
            String url = "https://free-api.heweather.net/s6/weather/";
            for (int i = 0; i < count && !flag; i++) {
                try {
                    Thread.sleep(500);
                    URL uri = new URL(url);
                    HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
                    connection.setRequestMethod("POST");
                    connection.setReadTimeout(5000);
                    connection.setConnectTimeout(10000);
                    connection.setRequestProperty("accept", "*/*");
                    //发送参数
                    connection.setDoOutput(true);
                    out = new PrintWriter(connection.getOutputStream());
                    out.print(param);
                    out.flush();
                    //接收结果
                    is = connection.getInputStream();
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    flag = true;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    log.info("和风天气官网下载任务异常....，重试："+i,e);
                }
                if (!flag) {
                    log.error("和风天气API下载异常,重试以超过3次");
                    continue;
                }
                flag = false;
            }
            String line;
            //缓冲逐行读取
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            if (StringUtils.isEmpty(sb.toString())) {
                log.info("获取实况天气任务失败。。。");
                return;
            }
            try {
                JSONObject jsonObject = JSONObject.parseObject(sb.toString());
                JSONArray jsonArray = (JSONArray) jsonObject.get("HeWeather6");
                String status = null;
                JSONObject basicObj = null;
                JSONObject updateObj = null;
                JSONObject nowObj = null;
                for (int i = 0; i < jsonArray.size(); i++) {
                    status = jsonArray.getJSONObject(i).getString("status");
                    basicObj = jsonArray.getJSONObject(i).getJSONObject("basic");
                    updateObj = jsonArray.getJSONObject(i).getJSONObject("update");
                    nowObj = jsonArray.getJSONObject(i).getJSONObject("now");
                }
                if (!"ok".equals(status)){
                    log.info("获取数据状态错误，error_code----->"+status);
                    throw new RuntimeException("和风天气API查询出错....");
                }
                Weather weather = new Weather();
                weather.setCid(basicObj.getString("cid"));
                weather.setLocation(basicObj.getString("location"));
                weather.setLat(basicObj.getString("lat"));
                weather.setLon(basicObj.getString("lon"));
                weather.setParentCity(basicObj.getString("parent_city"));
                weather.setCnty(basicObj.getString("cnty"));
                weather.setAdminArea(basicObj.getString("admin_area"));
                weather.setTz(basicObj.getString("tz"));
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                weather.setLoc(dateFormat.parse(updateObj.getString("loc")));
                weather.setFl(nowObj.getString("fl"));
                weather.setTmp(nowObj.getString("tmp"));
                weather.setWindDeg(nowObj.getString("wind_deg"));
                weather.setWindDir(nowObj.getString("wind_dir"));
                weather.setWindSc(nowObj.getString("wind_sc"));
                weather.setWindSpd(nowObj.getString("wind_spd"));
                Integer res = weatherService.saveWeatherInfo(weather);
                if (res > 0) {
                    log.info("新增实况天气信息成功...");
                } else {
                    log.info("新增实况天气信息失败。。。");
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.info("和风天气获取信息失败....,error："+e);
            }
            System.out.println(sb.toString());
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (is != null) {
                    is.close();
                }
                if (br != null) {
                    br.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (Exception ignored) {
            }
        }
    }
}
